package org.zoomdev.zoom.dao.impl;

import org.zoomdev.zoom.common.Destroyable;
import org.zoomdev.zoom.common.utils.Classes;
import org.zoomdev.zoom.dao.driver.DbStructFactory;
import org.zoomdev.zoom.dao.driver.Snapshot;
import org.zoomdev.zoom.dao.meta.TableMeta;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

public final class CachedDbStructFactory implements DbStructFactory, Destroyable {

    //保证与表名称不一样就行了
    private static final String NAME_AND_COMMENT_KEY_NAME = "#@names";
    private static final String ALL_TRIGGERS = "#@triggers";
    private static final String ALL_SEQUENCES = "#@sequences";
    private final DbStructFactory factory;
    /**
     * 缓存
     */
    private final ConcurrentMap<String, Object> pool = new ConcurrentHashMap<String, Object>();

    public CachedDbStructFactory(DbStructFactory factory) {
        this.factory = factory;
    }

    public <T> T get(String key) {
        return (T) pool.get(key);
    }

    @Override
    public List<String> getTableNames() {
        List<String> array = new ArrayList<>();
        for (TableNameAndComment data : getNameAndComments()) {
            array.add(data.getName());
        }
        return array;
    }


    @Override
    public TableMeta getTableMeta(final String tableName) {

        return (TableMeta) pool.computeIfAbsent(tableName, (String key) -> factory.getTableMeta(key));
    }


    @Override
    public List<TableNameAndComment> getNameAndComments() {
        return (List<TableNameAndComment>) pool.computeIfAbsent(NAME_AND_COMMENT_KEY_NAME, (String key) -> factory.getNameAndComments());
    }

    @Override
    public Map<String, Collection<String>> getTriggers() {
        return (Map<String, Collection<String>>) pool.computeIfAbsent(ALL_TRIGGERS, (String key) -> factory.getTriggers());
    }

    @Override
    public Collection<String> getSequences() {
        return (Collection<String>) pool.computeIfAbsent(ALL_SEQUENCES, (String key) -> factory.getSequences());
    }

    @Override
    public void fill(TableMeta tableMeta) {

    }

    @Override
    public void clearCache() {
        pool.clear();
    }

    @Override
    public Snapshot takeSnapshot() {
        return factory.takeSnapshot();
    }

    @Override
    public void destroy() {
        Classes.destroy(pool);
    }
}
